home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / tcpcmd < prev    next >
Text File  |  1994-01-08  |  10KB  |  362 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include "global.h"
  5. #include "timer.h"
  6. #include "mbuf.h"
  7. #include "netuser.h"
  8. #include "internet.h"
  9. #include "tcp.h"
  10. #include "cmdparse.h"
  11. #include "misc.h"
  12. #include "arc.h"
  13. #include "asy.h"
  14.  
  15. #include "os.h"
  16. #include "swis.h"
  17.  
  18. static int dotcpreset(int, char **);
  19. static int dohangup(int, char **);
  20. static int doirtt(int, char **);
  21. static int dortt(int, char **);
  22. static int dotcpkick(int, char **);
  23. static int domss(int, char **);
  24. static int dowindow(int, char **);
  25. static int dotcpstat(int, char **);
  26. static int tstat(void);
  27. static void state_tcp(struct tcb *);
  28.  
  29. /* TCP connection states */
  30. char *tcpstates[] = {
  31.         "Closed",
  32.         "Listen",
  33.         "SYN sent",
  34.         "SYN received",
  35.         "Established",
  36.         "FIN wait 1",
  37.         "FIN wait 2",
  38.         "Close wait",
  39.         "Closing",
  40.         "Last ACK",
  41.         "Time wait"
  42. };
  43.  
  44. /* TCP closing reasons */
  45. char *reasons[] = {
  46.         "Normal",
  47.         "Reset",
  48.         "Timeout",
  49.         "ICMP"
  50. };
  51.  
  52. static struct timer busy;
  53. static int busy_checks = 0;
  54. static int busy_limit  = 0;
  55. static BOOL busy_exit  = FALSE;
  56.  
  57. /* TCP subcommand table */
  58. struct cmds tcpcmds[] = {
  59.         "hangup", dohangup,   3, "tcp hangup <check> <after> [exit]",  NULLCHAR,
  60.         "irtt",   doirtt,     0, NULLCHAR,                      NULLCHAR,
  61.         "kick",   dotcpkick,  2, "tcp kick <tcb>",              NULLCHAR,
  62.         "mss",    domss,      0, NULLCHAR,                      NULLCHAR,
  63.         "reset",  dotcpreset, 2, "tcp reset <tcb>",             NULLCHAR,
  64.         "rtt",    dortt,      3, "tcp rtt <tcb> <val>",         NULLCHAR,
  65.         "status", dotcpstat,  0, NULLCHAR,                      NULLCHAR,
  66.         "window", dowindow,   0, NULLCHAR,                      NULLCHAR,
  67.         NULLCHAR,
  68. };
  69. int dotcp(int argc, char **argv)
  70. {
  71.         return subcmd(tcpcmds,argc,argv);
  72. }
  73.  
  74. /* Eliminate a TCP connection */
  75. static int dotcpreset(int argc, char **argv)
  76. {
  77.         register struct tcb *tcb;
  78.         extern char notval[];
  79.  
  80.         argc = argc;
  81.  
  82.         tcb = (struct tcb *)htol(argv[1]);
  83.         if(!tcpval(tcb)){
  84.                 cwprintf(NULL, notval);
  85.                 return 1;
  86.         }
  87.         close_self(tcb,RESET);
  88.         return 0;
  89. }
  90.  
  91. static void dotcpbusy(void *p)
  92. {
  93.   register int i;
  94.   register struct tcb *tcb;
  95.  
  96.   p = p;
  97.   start_timer(&busy);
  98.  
  99.   for (i = 0; i < NTCB; i++)
  100.   {
  101.     for (tcb = tcbs[i]; tcb != NULLTCB; tcb = tcb->next)
  102.     {
  103.       if (tcb->state > 3)
  104.       {
  105.         busy_checks = 0;
  106.         return;
  107.       }
  108.     }
  109.   }
  110.   busy_checks++;
  111.  
  112.   if (asy_scan())
  113.     cwprintf(NULL, "TCP checks clear = %d Hanging up after %d more\r\n", busy_checks, busy_limit - busy_checks);
  114.   else
  115.     busy_checks = 0;
  116.     
  117.   if (busy_checks == busy_limit)
  118.   {
  119.     iostop();
  120.     if (busy_exit)
  121.       net_exit();
  122.   }
  123. }
  124.  
  125. static int dohangup(int argc, char **argv)
  126. {
  127.   busy.func = dotcpbusy;
  128.   busy.arg = NULL;
  129.   busy_checks = 0;
  130.   busy_limit  = atoi(argv[2]);
  131.   cwprintf(NULL, "Check every %s seconds, hangup after %s clear checks\r\n", argv[1], argv[2]);
  132.   if (argc == 4 && strnicmp(argv[3], "exit", MIN(strlen(argv[3]), 4)) == 0)
  133.   {
  134.     busy_exit = TRUE;
  135.     cwprintf(NULL, "and exit program.\r\n");
  136.   }
  137.   if (busy_limit > 0)
  138.   {
  139.     set_timer(&busy, atol(argv[1]) * 1000L);
  140.     start_timer(&busy);
  141.   }
  142.   else
  143.   {
  144.     stop_timer(&busy);
  145.   }
  146.  
  147.   return(0);
  148. }
  149.  
  150. /* Set initial round trip time for new connections */
  151. static int doirtt(int argc, char **argv)
  152. {
  153.         if(argc < 2)
  154.                 cwprintf(NULL, "%lu\r\n",tcp_irtt);
  155.         else
  156.                 tcp_irtt = atol(argv[1]);
  157.         return 0;
  158. }
  159.  
  160. /* Set smoothed round trip time for specified TCB */
  161. static int dortt(int argc, char **argv)
  162. {
  163.         register struct tcb *tcb;
  164.         extern char notval[];
  165.  
  166.         argc = argc;
  167.  
  168.         tcb = (struct tcb *)htol(argv[1]);
  169.         if(!tcpval(tcb)){
  170.                 cwprintf(NULL, notval);
  171.                 return 1;
  172.         }
  173.         tcb->srtt = atol(argv[2]);
  174.         return 0;
  175. }
  176.  
  177. /* Force a retransmission */
  178. static int dotcpkick(int argc, char **argv)
  179. {
  180.         register struct tcb *tcb;
  181.         extern char notval[];
  182.  
  183.         argc = argc;
  184.  
  185.         tcb = (struct tcb *)htol(argv[1]);
  186.         if(kick_tcp(tcb) == -1){
  187.                 cwprintf(NULL, notval);
  188.                 return 1;
  189.         }
  190.         return 0;
  191. }
  192.  
  193. /* Set default maximum segment size */
  194. static int domss(int argc, char **argv)
  195. {
  196.         if(argc < 2)
  197.                 cwprintf(NULL, "%u\r\n",tcp_mss);
  198.         else
  199.                 tcp_mss = atoi(argv[1]);
  200.         return 0;
  201. }
  202.  
  203. /* Set default window size */
  204. static int dowindow(int argc, char **argv)
  205. {
  206.         if(argc < 2)
  207.                 cwprintf(NULL, "%u\r\n",tcp_window);
  208.         else
  209.                 tcp_window = atoi(argv[1]);
  210.         return 0;
  211. }
  212.  
  213. /* Display status of TCBs */
  214. static int dotcpstat(int argc, char **argv)
  215. {
  216.         register struct tcb *tcb;
  217.         extern char notval[];
  218.  
  219.         if(argc < 2){
  220.                 tstat();
  221.         } else {
  222.                 tcb = (struct tcb *)htol(argv[1]);
  223.                 if(tcpval(tcb))
  224.                         state_tcp(tcb);
  225.                 else
  226.                         cwprintf(NULL, notval);
  227.         }
  228.         return 0;
  229. }
  230.  
  231. /* Dump TCP stats and summary of all TCBs
  232.  *     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  233.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  234.  */
  235. static int tstat(void)
  236. {
  237.         register int i;
  238.         register struct tcb *tcb;
  239.  
  240.         cwprintf(NULL, "conout %u conin %u reset out %u runt %u chksum err %u bdcsts %u\r\n",
  241.                 tcp_stat.conout,tcp_stat.conin,tcp_stat.resets,tcp_stat.runt,
  242.                 tcp_stat.checksum,tcp_stat.bdcsts);
  243.         cwprintf(NULL, "    &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State\r\n");
  244.         for(i=0;i<NTCB;i++){
  245.                 for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
  246.                         cwprintf(NULL, "%8lx%6u%6u  ",(long)tcb,tcb->rcvcnt,tcb->sndcnt);
  247.                         cwprintf(NULL, "%-23s",psocket(&tcb->conn.local));
  248.                         cwprintf(NULL, "%-23s",psocket(&tcb->conn.remote));
  249.                         cwprintf(NULL, "%-s",tcpstates[tcb->state]);
  250.                         if(tcb->state == LISTEN && (tcb->flags & CLONE))
  251.                                 cwprintf(NULL, " (S)");
  252.                         cwprintf(NULL, "\r\n");
  253.                 }
  254.         }
  255.         return 0;
  256. }
  257. /* Dump a TCP control block in detail */
  258. static void state_tcp(struct tcb *tcb)
  259. {
  260.         int32 sent,recvd;
  261.  
  262.         if(tcb == NULLTCB)
  263.                 return;
  264.         /* Compute total data sent and received; take out SYN and FIN */
  265.         sent = tcb->snd.una - tcb->iss; /* Acknowledged data only */
  266.         recvd = tcb->rcv.nxt - tcb->irs;
  267.         switch(tcb->state){
  268.         case LISTEN:
  269.         case SYN_SENT:          /* Nothing received or acked yet */
  270.                 sent = recvd = 0;       
  271.                 break;
  272.         case SYN_RECEIVED:
  273.                 recvd--;        /* Got SYN, no data acked yet */
  274.                 sent = 0;
  275.                 break;
  276.         case ESTABLISHED:       /* Got and sent SYN */
  277.         case FINWAIT1:          /* FIN not acked yet */
  278.                 sent--;
  279.                 recvd--;
  280.                 break;
  281.         case FINWAIT2:          /* Our SYN and FIN both acked */
  282.                 sent -= 2;
  283.                 recvd--;
  284.                 break;
  285.         case CLOSE_WAIT:        /* Got SYN and FIN, our FIN not yet acked */
  286.         case CLOSING:
  287.         case LAST_ACK:
  288.                 sent--;
  289.                 recvd -= 2;
  290.                 break;
  291.         case TIME_WAIT:         /* Sent and received SYN/FIN, all acked */
  292.                 sent -= 2;
  293.                 recvd -= 2;
  294.                 break;
  295.         }
  296.         cwprintf(NULL, "Local: %s",psocket(&tcb->conn.local));
  297.         cwprintf(NULL, " Remote: %s",psocket(&tcb->conn.remote));
  298.         cwprintf(NULL, " State: %s\r\n",tcpstates[tcb->state]);
  299.         cwprintf(NULL, "      Init seq    Unack     Next Resent CWind Thrsh  Wind  MSS Queue      Total\r\n");
  300.         cwprintf(NULL, "Send:");
  301.         cwprintf(NULL, "%9lx",tcb->iss);
  302.         cwprintf(NULL, "%9lx",tcb->snd.una);
  303.         cwprintf(NULL, "%9lx",tcb->snd.nxt);
  304.         cwprintf(NULL, "%7lu",tcb->resent);
  305.         cwprintf(NULL, "%6u",tcb->cwind);
  306.         cwprintf(NULL, "%6u",tcb->ssthresh);
  307.         cwprintf(NULL, "%6u",tcb->snd.wnd);
  308.         cwprintf(NULL, "%5u",tcb->mss);
  309.         cwprintf(NULL, "%6u",tcb->sndcnt);
  310.         cwprintf(NULL, "%11lu\r\n",sent);
  311.  
  312.         cwprintf(NULL, "Recv:");
  313.         cwprintf(NULL, "%9lx",tcb->irs);
  314.         cwprintf(NULL, "         ");
  315.         cwprintf(NULL, "%9lx",tcb->rcv.nxt);
  316.         cwprintf(NULL, "%7lu",tcb->rerecv);
  317.         cwprintf(NULL, "      ");
  318.         cwprintf(NULL, "      ");
  319.         cwprintf(NULL, "%6u",tcb->rcv.wnd);
  320.         cwprintf(NULL, "     ");
  321.         cwprintf(NULL, "%6u",tcb->rcvcnt);
  322.         cwprintf(NULL, "%11lu\r\n",recvd);
  323.  
  324.         if(tcb->reseq != (struct reseq *)NULL){
  325.                 register struct reseq *rp;
  326.  
  327.                 cwprintf(NULL, "Reassembly queue:\r\n");
  328.                 for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
  329.                         cwprintf(NULL, "  seq x%lx %u bytes\r\n",rp->seg.seq,rp->length);
  330.                 }
  331.         }
  332.         if(tcb->backoff > 0)
  333.                 cwprintf(NULL, "Backoff %u ",tcb->backoff);
  334.         if(tcb->flags & RETRAN)
  335.                 cwprintf(NULL, "Retrying ");
  336.         switch(tcb->timer.state){
  337.         case TIMER_STOP:
  338.                 cwprintf(NULL, "Timer stopped ");
  339.                 break;
  340.         case TIMER_RUN:
  341.                 cwprintf(NULL, "Timer running (%ld/%ld ms) ",
  342.                  (long)MSPTICK * (tcb->timer.start - tcb->timer.count),
  343.                  (long)MSPTICK * tcb->timer.start);
  344.                 break;
  345.         case TIMER_EXPIRE:
  346.                 cwprintf(NULL, "Timer expired ");
  347.         }
  348.         cwprintf(NULL, "SRTT %ld ms Mean dev %ld ms\r\n",tcb->srtt,tcb->mdev);
  349. }
  350.  
  351. int rem_kick(void)
  352. {
  353.         register int i;
  354.         register struct tcb *tcb;
  355.         for(i=0;i<NTCB;i++){
  356.                 for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
  357.                         kick_tcp(tcb);
  358.                 }
  359.         }
  360.         return 0;
  361. }
  362.